package com.company;

import lombok.Data;
import net.sf.cglib.beans.BeanCopier;
import org.apache.commons.lang3.time.StopWatch;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;

/**
 * @date : 2022/7/26 15:28
 * 为什么阿里巴巴禁止使用Apache Beanutils进行属性的copy？
 * https://mp.weixin.qq.com/s/3XX-Lu1KrKEc3IfB9Iqz5A
 * 在性能方面，Spring BeanUtils和Cglib BeanCopier表现比较不错，而Apache PropertyUtils、Apache BeanUtils以及Dozer则表现的很不好。
 * 所以，如果考虑性能情况的话，建议大家不要选择Apache PropertyUtils、Apache BeanUtils以及Dozer等工具类。
 * 很多人会不理解，为什么大名鼎鼎的Apache开源出来的的类库性能确不高呢？这不像是Apache的风格呀，这背后导致性能低下的原因又是什么呢？
 * 其实，是因为Apache BeanUtils力求做得完美, 在代码中增加了非常多的校验、兼容、日志打印等代码，过度的包装导致性能下降严重。
 * 拷贝动作需要 set/get 方法
 */

public class P026_ApacheBeanUtils {

    public static void main(String[] args) throws Exception {

        PersonDO personDO = new PersonDO();
        personDO.setName("Alice");
        personDO.setAge(26);
        personDO.setBirthday(new Date());
        personDO.setId(1);

        PersonDTO personDTO = new PersonDTO();
        org.apache.commons.beanutils.BeanUtils.copyProperties(personDTO, personDO);
        System.out.println(personDO);
        System.out.println(personDTO);

//        mappingBySpringBeanUtils(personDO, 100);
//        mappingBySpringBeanUtils(personDO, 1000);
//        mappingBySpringBeanUtils(personDO, 10000);
//        mappingBySpringBeanUtils(personDO, 100000);
//        mappingBySpringBeanUtils(personDO, 1000000);
//
//        mappingByCglibBeanCopier(personDO, 100);
//        mappingByCglibBeanCopier(personDO, 1000);
//        mappingByCglibBeanCopier(personDO, 10000);
//        mappingByCglibBeanCopier(personDO, 100000);
//        mappingByCglibBeanCopier(personDO, 1000000);
//
//        mappingByApachePropertyUtils(personDO, 100);
//        mappingByApachePropertyUtils(personDO, 1000);
//        mappingByApachePropertyUtils(personDO, 10000);
//        mappingByApachePropertyUtils(personDO, 100000);
//        mappingByApachePropertyUtils(personDO, 1000000);
//
//        mappingByApacheBeanUtils(personDO, 100);
//        mappingByApacheBeanUtils(personDO, 1000);
//        mappingByApacheBeanUtils(personDO, 10000);
//        mappingByApacheBeanUtils(personDO, 100000);
//        mappingByApacheBeanUtils(personDO, 1000000);
    }

    private static void mappingByApachePropertyUtils(PersonDO personDO, int times) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        StopWatch stopwatch = new StopWatch();
        stopwatch.start();
        for (int i = 0; i < times; i++) {
            PersonDTO personDTO = new PersonDTO();
            org.apache.commons.beanutils.PropertyUtils.copyProperties(personDTO, personDO);
        }
        stopwatch.stop();
        System.out.println("mappingByApachePropertyUtils cost :" + stopwatch.getTime());
    }

    private static void mappingByApacheBeanUtils(PersonDO personDO, int times) throws InvocationTargetException, IllegalAccessException {
        StopWatch stopwatch = new StopWatch();
        stopwatch.start();
        for (int i = 0; i < times; i++) {
            PersonDTO personDTO = new PersonDTO();
            org.apache.commons.beanutils.BeanUtils.copyProperties(personDTO, personDO);
        }
        stopwatch.stop();
        System.out.println("mappingByApacheBeanUtils cost :" + stopwatch.getTime());
    }

    private static void mappingByCglibBeanCopier(PersonDO personDO, int times) {
        StopWatch stopwatch = new StopWatch();
        stopwatch.start();
        for (int i = 0; i < times; i++) {
            PersonDTO personDTO = new PersonDTO();
            BeanCopier copier = BeanCopier.create(PersonDO.class, PersonDTO.class, false);
            copier.copy(personDO, personDTO, null);
        }
        stopwatch.stop();
        System.out.println("mappingByCglibBeanCopier cost :" + stopwatch.getTime());
    }

//    private static void mappingBySpringBeanUtils(PersonDO personDO, int times) throws Exception {
//        StopWatch stopwatch = new StopWatch();
//        stopwatch.start();
//        for (int i = 0; i < times; i++) {
//            PersonDTO personDTO = new PersonDTO();
//            org.springframework.beans.BeanUtils.copyProperties(personDO, personDTO);
//        }
//        stopwatch.stop();
//        System.out.println("mappingBySpringBeanUtils cost :" + stopwatch.getTime());
//
//    }

    @Data
    public static class PersonDO {
        private Integer id;

        private String name;

        private Integer age;

        private Date birthday;
    }


    public static class PersonDTO {
        private String name;

        private Integer age;

        private Date birthday;
    }
}
